/**
 * 事件发射器
 */
export namespace Emitter {
    const eventMap: Record<string, { target: any, callback: Function }[]> = Object.create(null)

    export function on(name: string, callback: Function, target?: any) {
        if (eventMap[name]) {
            eventMap[name].push({ target: target, callback: callback })
        } else {
            eventMap[name] = [{ target: target, callback: callback }]
        }
    }

    export function once(name: string, callback: Function, target?: any) {
        const cb = () => {
            callback.apply(target)
            off(name, cb)
        }
        on(name, cb)
    }

    export function off(name: string, callback?: Function) {
        const events = eventMap[name]
        if (!events) {
            return
        }

        if (!callback) {
            delete eventMap[name]
            return
        }

        for (let i = events.length - 1; i >= 0; i--) {
            if (events[i].callback == callback) {
                events.splice(i, 1)
            }
        }
    }

    export function offTarget(target: any) {
        for (const name in eventMap) {
            const events = eventMap[name]
            for (let i = events.length - 1; i >= 0; i--) {
                if (events[i].target == target) {
                    events.splice(i, 1)
                }
            }
        }
    }

    export function emit(name: string, ...args: any) {
        eventMap[name]?.forEach(evnet => evnet.callback.apply(evnet.target, args))
    }

    export function has(name: string) {
        return !!eventMap[name]?.length
    }
}
